package com.hxexp.weixin.mvc.pay.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hxexp.weixin.common.cache.TokenCacheManager;
import com.hxexp.weixin.common.exception.ServiceException;
import com.hxexp.weixin.common.web.HttpUtil;
import com.hxexp.weixin.constant.CarryFreeTicketFlag;
import com.hxexp.weixin.constant.CookieName;
import com.hxexp.weixin.constant.IdentificationType;
import com.hxexp.weixin.constant.StartStationsId;
import com.hxexp.weixin.constant.StringConstant;
import com.hxexp.weixin.constant.TicketType;
import com.hxexp.weixin.constant.WebAppVersion;
import com.hxexp.weixin.hpe.api.login.model.LoginResultBean;
import com.hxexp.weixin.hpe.api.orderdetail.model.OrderDetailResultBean;
import com.hxexp.weixin.hpe.api.orderdetail.model.OrderTicketInfoBean;
import com.hxexp.weixin.hpe.api.orderpayment.model.PrepayOrderParamBean;
import com.hxexp.weixin.hpe.api.orderpayment.model.PrepayOrderResultBean;
import com.hxexp.weixin.mvc.order.service.OrderService;
import com.hxexp.weixin.mvc.pay.service.PayService;

/**
 * 支付控制器
 *
 * @author li.jiang
 * @author wang.bin
 */
@Controller
@RequestMapping(value = "/pay")
public final class PayController {
    private static final Logger LOGGER = LoggerFactory.getLogger(PayController.class);
    private static final int PREPAY_SUCCESS = 1; // 预支付订单调用成功的返回结果
    @Autowired
    private PayService payService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private TokenCacheManager tokenCacheManager;
    /**
     * 设置页面需要的常量
     *
     * @return
     */
    @ModelAttribute("constant")
    public Map<String, String> setConstant() {
        Map<String, String> map = new HashMap<String, String>();

        map.put("carry", CarryFreeTicketFlag.CARRY);// 携带免票
        map.put("nocarry", CarryFreeTicketFlag.NONCARRY);// 不携带免票
        map.put("idcard", IdentificationType.IDCARD);// 身份证
        map.put("appver_nc", WebAppVersion.NC);// 南充当代运业网站版本编号
        map.put("appver_ylns", WebAppVersion.YLNS);
        map.put("lzzx_stationid", StartStationsId.LZZX); // 泸州客运中心站ID

        return map;
    }

    /**
     * 订单支付页面
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/confirm")
    public String paymentConfirm(HttpServletRequest request, String orderId, String ptiks, Model model,
                                 @CookieValue(value = CookieName.OPENID, defaultValue = StringConstant.BLANK) String openid,
                                 @CookieValue(value = CookieName.TOKEN, defaultValue = StringConstant.BLANK) String token) {
        // 从缓存中获取登陆用户信息
        LoginResultBean loginResult = tokenCacheManager.getUserFromCache(token);

        // 预支付订单参数
        PrepayOrderParamBean prepayOrderParam = new PrepayOrderParamBean();
        prepayOrderParam.setUserName(loginResult.getFullname());

        paramSetting(prepayOrderParam, orderId, model, loginResult.getUserId());

        // 解密openid
        //        openid = AESHelper.decryptString(openid, AppDevConstant.OPENIDSECRET);由于服务器运行环境的问题，已取消对openid加密,因此这里不用解密
        LOGGER.debug("解密后的openid: {}", openid);
        // 设置预付订单参数
        prepayOrderParam.setOpenId(openid); // 微信服务号订阅用户的openid
        prepayOrderParam.setOrderTime(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss")); // 下单时间
        prepayOrderParam.setTerminalType("phone"); // 渠道类型
        prepayOrderParam.setPayType("JSAPI"); // 支付类型
        prepayOrderParam.setRemoteAddr(HttpUtil.getIpAddr(request)); // 终端IP地址

        PrepayOrderResultBean prepayOrderResult = new PrepayOrderResultBean();
        String prepayId = ""; // 预支付交易会话标识

        try {
            prepayOrderResult = payService.prepayOrder(prepayOrderParam); // 预支付下单，为了获得调微信JSAPI支付需要的prepayId
            if (prepayOrderResult.getRet() == PREPAY_SUCCESS) {
                prepayId = prepayOrderResult.getPrepayId();
            }
        } catch (ServiceException e) {
            LOGGER.error("预付订单操作发生异常", e);
        }

        ObjectMapper mapper = new ObjectMapper();
        try {
            String jsonPayParam = mapper.writeValueAsString(payService.generatePayParam(prepayId));
            model.addAttribute("jsApiParam", jsonPayParam); // 将微信支付的参数转换成JSON字符串
            LOGGER.debug("************微信支付需要的参数：{}", jsonPayParam);
        } catch (JsonGenerationException e) {
            LOGGER.error("json生成异常", e);
        } catch (JsonMappingException e) {
            LOGGER.error("json映射异常", e);
        } catch (IOException e) {
            LOGGER.error("IO异常", e);
        }

        model.addAttribute("ptiks", ptiks);
        return "order_payment";
    }

    /**
     * 设定订单支付页面需要的参数值
     *
     * @param
     * @return
     */
    private void paramSetting(PrepayOrderParamBean prepayOrderParam, String orderId,
                              Model model, String userId) {
        OrderDetailResultBean orderDetailResult = new OrderDetailResultBean();
        String servicePriceTotal = ""; // 服务费总计
        List<OrderTicketInfoBean> ticketList = new ArrayList<OrderTicketInfoBean>(); // 订单车票信息列表

        try {
            int fullTicketNum = 0; // 全票数量
            int halfTicketNum = 0; // 半票数量
            int freeTicketNum = 0; // 免票数量
            BigDecimal totalAmount = new BigDecimal("0.00");

            orderDetailResult = orderService.getOrderDetail(orderId); // 查询订单详情
            ticketList = orderDetailResult.getTicketList();
            if (ticketList == null) {
                ticketList = new ArrayList<OrderTicketInfoBean>();
            }

            // 计算全票、半票、免票数量
            for (OrderTicketInfoBean orderTicket : ticketList) {
                if (TicketType.FULLTICKET.equals(orderTicket.getTicketType())) {
                    fullTicketNum++;
                } else if (TicketType.HALFTICKET.equals(orderTicket.getTicketType())) {
                    halfTicketNum++;
                } else if (TicketType.FREETICKET.equals(orderTicket.getTicketType())) {
                    freeTicketNum++;
                    fullTicketNum++;
                }
                // 计算服务费总价
                BigDecimal serviceprice = new BigDecimal(orderTicket.getServicePrice());
                BigDecimal amount = totalAmount.add(serviceprice);
                totalAmount = amount;
            }

            double total = totalAmount.doubleValue();
            java.text.DecimalFormat df = new java.text.DecimalFormat("#0.00");
            servicePriceTotal = df.format(total);
            orderDetailResult.setFullTicketNum(fullTicketNum + "");
            orderDetailResult.setHalfTicketNum(halfTicketNum + "");
            orderDetailResult.setFreeTicketNum(freeTicketNum + "");
            orderDetailResult.setServiceprice(servicePriceTotal);
            orderDetailResult.setTotalprices(orderDetailResult.getTotalPrice());
        } catch (ServiceException e) {
            LOGGER.error("调用订单详细信息发生异常", e);
        }

        model.addAttribute("ticketList", ticketList);
        model.addAttribute("orderPaymentInfo", orderDetailResult);
        LOGGER.debug("***********设定订单支付页面参数时返回的订单详情: {}", orderDetailResult);
        // 设置预付订单参数
        prepayOrderParam.setOrderId(orderDetailResult.getOrderId()); // 订单号
        prepayOrderParam.setProductId(orderDetailResult.getStartStationName()); // 产品编号
        prepayOrderParam.setProductName(orderDetailResult.getStartStationName() + "-" + orderDetailResult.getArriveStationName()); // 产品名称
        prepayOrderParam.setProductNum((Integer.parseInt(orderDetailResult.getHalfTicketNum()) + Integer.parseInt(orderDetailResult.getFullTicketNum())) + ""); // 产品数量
        prepayOrderParam.setOrderAmount(orderDetailResult.getTotalprices()); // 订单金额
    }

    /**
     * 支付结果页面
     *
     * <br/>
     * 完成微信支付后打开该页面
     *
     * @param orderpnr
     *            订单编号
     * @return
     */
    @RequestMapping(value = "/result")
    public String paymentResult(String orderpnr, String ptiks, String startStationId, Model model) {
        LOGGER.debug("订单{},已完成支付", orderpnr);
        try {
            // 记录乘客购票信息
            payService.savePassengerTicketRecord(ptiks);
        } catch (ServiceException e) {
            LOGGER.error("保存乘客购票记录发生异常", e);
        }
        model.addAttribute("orderpnr", orderpnr);
        model.addAttribute("startStationId", startStationId);

        return "payment_result";
    }

}
